qdnslookup_crash
authorDebian Qt/KDE Maintainers <debian-qt-kde@lists.debian.org>
Fri, 9 Feb 2018 13:40:07 +0000 (13:40 +0000)
committerDmitry Shachnev <mitya57@debian.org>
Fri, 9 Feb 2018 13:40:07 +0000 (13:40 +0000)
Gbp-Pq: Name qdnslookup_crash.diff

src/network/kernel/qdnslookup_unix.cpp

index 1da00813ce21b0127d49f9626f4dcdaca58f3018..ce1ec6442a645cd1dd2eb584c49867e9c929d3e0 100644 (file)
@@ -42,6 +42,7 @@
 #if QT_CONFIG(library)
 #include <qlibrary.h>
 #endif
+#include <qvarlengtharray.h>
 #include <qscopedpointer.h>
 #include <qurl.h>
 #include <private/qnativesocketengine_p.h>
@@ -58,6 +59,8 @@
 #  include <gnu/lib-names.h>
 #endif
 
+#include <cstring>
+
 QT_BEGIN_NAMESPACE
 
 #if QT_CONFIG(library)
@@ -137,7 +140,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
 
     // Initialize state.
     struct __res_state state;
-    memset(&state, 0, sizeof(state));
+    std::memset(&state, 0, sizeof(state));
     if (local_res_ninit(&state) < 0) {
         reply->error = QDnsLookup::ResolverError;
         reply->errorString = tr("Resolver initialization failed");
@@ -189,11 +192,25 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
     QScopedPointer<struct __res_state, QDnsLookupStateDeleter> state_ptr(&state);
 
     // Perform DNS query.
-    unsigned char response[PACKETSZ];
-    memset(response, 0, sizeof(response));
-    const int responseLength = local_res_nquery(&state, requestName, C_IN, requestType, response, sizeof(response));
+    QVarLengthArray<unsigned char, PACKETSZ> buffer(PACKETSZ);
+    std::memset(buffer.data(), 0, buffer.size());
+    int responseLength = local_res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size());
+    if (Q_UNLIKELY(responseLength > PACKETSZ)) {
+        buffer.resize(responseLength);
+        std::memset(buffer.data(), 0, buffer.size());
+        responseLength = local_res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size());
+        if (Q_UNLIKELY(responseLength > buffer.size())) {
+            // Ok, we give up.
+            reply->error = QDnsLookup::ResolverError;
+            reply->errorString.clear(); // We cannot be more specific, alas.
+            return;
+        }
+    }
 
-    // Check the response header.
+    unsigned char *response = buffer.data();
+    // Check the response header. Though res_nquery returns -1 as a
+    // responseLength in case of error, we still can extract the
+    // exact error code from the response.
     HEADER *header = (HEADER*)response;
     const int answerCount = ntohs(header->ancount);
     switch (header->rcode) {